package com.service.http.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * 描述：
 * http服务
 * @author xianggj
 * @Date 2021/8/30 14:24
 **/
@Slf4j
public class HttpService {

    @Autowired
    private RestTemplate restTemplate;


    public String get(String url, String... params){
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class, params);
        if (forEntity.getStatusCode().is2xxSuccessful()){
            String result = forEntity.getBody();
            return result;
        } else{
            log.error("code:{}" ,forEntity.getStatusCodeValue());
            log.error("message:{}" ,forEntity.toString());
        }
        return null;
    }

    /**
     * get请求 带头
     * @param url
     * @param headers
     * @return
     */
    public String get(String url, HttpHeaders headers){
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        ResponseEntity<String> resEntity = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class);
        if (resEntity.getStatusCode().is2xxSuccessful()){
            String result = resEntity.getBody();
            return result;
        } else{
            log.error("code:{}" ,resEntity.getStatusCodeValue());
            log.error("message:{}" ,resEntity.toString());
        }
        return null;
    }

    public String get(String url, Map<String, String> params){
        ResponseEntity<String> forEntity = restTemplate.getForEntity(url, String.class, params);
        if (forEntity.getStatusCode().is2xxSuccessful()){
            String result = forEntity.getBody();
            return result;
        } else{
            log.error("code:{}" ,forEntity.getStatusCodeValue());
            log.error("message:{}" ,forEntity.toString());
        }
        return null;
    }

    public String post(String url, JSONObject jsonObject){
        restTemplate.getMessageConverters().add(new FastJsonHttpMessageConverter());
        String result = restTemplate.postForObject(url, jsonObject, String.class);
        return result;
    }

    public String post4Form(String url, MultiValueMap<String, Object> postParameters ){
        HttpHeaders headers = new HttpHeaders();
        headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
        HttpEntity<MultiValueMap<String, Object>> r = new HttpEntity<>(postParameters, headers);
        String result = restTemplate.postForObject(url, r, String.class);
        return result;
    }

    public String post(String url, Map<String, Object> params){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, Object>> request =
                new HttpEntity<>(convertMapToMultiValueMap(params), headers);
        ResponseEntity<String> forEntity =
                restTemplate.postForEntity(url, request, String.class);
        if (forEntity.getStatusCode().is2xxSuccessful()){
            String result = forEntity.getBody();
            return result;
        } else{
            log.error("code:{}" ,forEntity.getStatusCodeValue());
            log.error("message:{}" ,forEntity.toString());
        }
        return null;
    }

    public String postWithCookie(String url, Map<String, Object> params, List<String> cookieList){
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.put("Cookie", cookieList);
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
        HttpEntity<MultiValueMap<String, Object>> request =
                new HttpEntity<>(convertMapToMultiValueMap(params), headers);
        ResponseEntity<String> forEntity =
                restTemplate.postForEntity(url, request, String.class);
        if (forEntity.getStatusCode().is2xxSuccessful()){
            String result = forEntity.getBody();
            return result;
        } else{
            log.error("code:{}" ,forEntity.getStatusCodeValue());
            log.error("message:{}" ,forEntity.toString());
        }
        return null;
    }



    public String upload(String url, File file, String fileName){
        FileSystemResource resource = new FileSystemResource(file);
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        //先写死 后面可以修改
        param.add("fileName", fileName);
        param.add("file", resource);
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("multipart/form-data");
        headers.setContentType(type);
        TimeInterval timer = DateUtil.timer();
        String result = restTemplate.postForObject(url, param, String.class);
        System.out.println("times："+timer.interval() + "ms");
        return result;
    }

    public String upload(String url, InputStream inputStream, String fileName){
        Resource resource = new InputStreamResource(inputStream) {
            @Override
            public String getFilename() {
                return fileName;
            }

            @Override
            public long contentLength() throws IOException {
                long estimate = inputStream.available();
                return estimate == 0 ? 1 : estimate;
            }

        };
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
        param.add("file", resource);
        //设置请求头
        HttpHeaders headers = new HttpHeaders();
        MediaType type = MediaType.parseMediaType("multipart/form-data");
        headers.setContentType(type);
        TimeInterval timer = DateUtil.timer();
        String result = restTemplate.postForObject(url, param, String.class);
        System.out.println("总耗时："+timer.interval() + "ms");
        return result;
    }

    public byte[] download(String url, Map<String, Object> params){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        TimeInterval timer = DateUtil.timer();
        ResponseEntity<byte[]> entity = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), byte[].class, params);
        byte[] body = entity.getBody();
        System.out.println("总耗时："+timer.interval() + "ms");
        return body;
    }

    public byte[] downloadPost(String url, Map<String, Object> params){
        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        HttpEntity<MultiValueMap<String, Object>> request =  new HttpEntity<>(convertMapToMultiValueMap(params), headers);
        ResponseEntity<byte[]> forEntity = restTemplate.postForEntity(url, request, byte[].class);
        byte[] body = forEntity.getBody();
        return body;
    }

    private MultiValueMap<String, Object> convertMapToMultiValueMap(Map<String, Object> param){
        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>();
        for (Map.Entry<String, Object> entry : param.entrySet()) {
            if(entry.getValue() instanceof List) {
                multiValueMap.put(entry.getKey(), (List<Object>) entry.getValue());
            } else {
                multiValueMap.add(entry.getKey(), entry.getValue());
            }
        }
        return multiValueMap;
    }

}
